feat(skills): skills.auto_load pins skills into every new session (salvage #74060/#26840) - #92048
Conversation
૮ >ﻌ< ა ci reviewran on 4b7188c — fix(skills): auto-load resolves under the agent's own home a
|
|
Cross-reference: #68608 (open, CI green) also changes |
This salvage does the two hard things right. First, cache safety by construction: auto-load resolves once per agent lifecycle and the exact rendered bytes are reused across model switches, compression, and static-prefix restoration ( The CLI adaptation to the backgrounded Minor points:
|
…rompt `skills.auto_load: [name, ...]` in config.yaml renders the listed skills as fully loaded skill blocks in the system prompt of every new agent — CLI, TUI, gateway, cron and API — the persistent counterpart of `-s`. Missing or operator-disabled names are warned about and skipped; a config typo never blocks session start. Re-implementation of #26840 by @ArcherQAQ (via #74060) against current main — the original patch targeted the pre-decomposition cli.py / system_prompt.py god files; design and diagnosis preserved. The loader reuses `_load_skill_blocks` (same disabled gate and Curator usage bump as `-s`) instead of a parallel loop.
The system prompt must stay byte-stable for the life of a conversation:
`_auto_load_skills_result` is seeded in `_SESSION_STATE` and filled on
the FIRST prompt build only (HERMES_IGNORE_RULES captured then too), so
model switches, compression and static-prefix restoration reuse the
exact rendered bytes rather than re-reading config or skill files.
CLI: auto_load renders in the existing background `--skills` preload
thread (real session id for ${HERMES_SESSION_ID}), `-s` names dedupe
against the auto-loaded canonical names via
`build_preloaded_skills_prompt(excluded_loaded_names=)`, the activated
skills line shows auto_load first, and the lazily built agent is seeded
with the pre-resolved bytes. `--ignore-rules` skips auto-load with the
rest of the auto-injected context.
Re-implementation of #74060 by @ctaylor86 against current main.
42f27c7 to
756ff37
Compare
…internal forks Why: build_auto_load_prompt read config via ambient load_config_readonly() and looked skills up under the ambient SKILLS_DIR. Gateway bot threads lose the HERMES_HOME ContextVar, so a bot profile's pinned skills came from the launch profile — the docs promise profile scoping. _auto_load_parts now passes home_override=_agent_home(agent) and build_auto_load_prompt binds it for config, disabled-list and <home>/skills lookup, the same seam _skills_prompt uses via skills_dir_override. _auto_load_parts was unconditional and injected pinned SKILL.md bytes into delegate children, curator/background_review forks and gateway hygiene agents; it now mirrors _skills_prompt's gate (nothing without the skills toolset) and returns [] when skip_context_files is set. cli.py's HERMES_IGNORE_RULES check used == "1" while system_prompt used is_truthy_value; both use is_truthy_value now. Tests stay at 4: the build test asserts the home-scoped resolution, the ignore-rules test also covers the subagent / no-skills-toolset gates.
Summary
skills.auto_loadinconfig.yamlnow pins skills as fully loaded at the start of every new session — CLI, TUI, gateway, cron, and API agents all included — the "always-on skill" pattern Cursor shipped as Custom Modes in its Aug 19, 2026 changelog.Salvages #74060 by @ctaylor86 (itself an authorship-preserving salvage of #26840 by @ArcherQAQ, whose feature commit leads the branch) onto current
main, adapted to the backgrounded--skillspreload that landed since.Their mechanism vs ours
--ignore-rules/HERMES_IGNORE_RULES=1suppresses auto-load with the rest of the auto-injected context. Explicit--skillsrequests dedupe against auto-load by canonical name.Changes
agent/skill_commands.py:resolve_auto_load_skills()+build_auto_load_prompt()(purpose-built activation note; same disabled-skill gate and Curator usage bump as--skills)agent/system_prompt.py: resolve-once injection in the shared prompt path (all agent surfaces), lifecycle-stableagent/agent_init.py,hermes_cli/cli_agent_setup_mixin.py: per-agent resolve-once cache, CLI hands its pre-resolved result to the lazily built agentcli.py: auto-load resolution after session-ID creation; adaptation to current main — the--skillspayload load is now a background thread joined byfinalize_preloaded_skills(), so the dedup set is passed into the background loader and the activated-skills display merges at finalize time (auto_load first)hermes_cli/config_defaults.py:skills.auto_load: []defaultwebsite/docs/user-guide/cli.md(new section from the original PR) +website/docs/user-guide/configuration.mdValidation
tests/agent/test_skills_auto_load.py+tests/cli/test_cli_preloaded_skills.pytest_system_prompt,test_prompt_builder,test_prompt_caching,test_prompt_cache_boundary,test_prompt_cache_scope)HERMES_HOME, real skill files, realbuild_system_prompt_partson a realAIAgent)HERMES_IGNORE_RULESsuppression ✓scripts/audit_pr_attribution.py --fixCloses #26840. Closes #74060.
Infographic